package wangjg.dbfx.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.sql.SQLException;
import java.util.List;

import javax.sql.rowset.CachedRowSet;

import wangjg.dbfx.JdbcException;
import wangjg.dbfx.JdbcSession;
import wangjg.dbfx.SessionFactory;
import wangjg.dbfx.mapping.EntityInfo;
import wangjg.dbfx.mapping.EntityInfoManager;
import wangjg.dbfx.mapping.ResultMapping;

public class BasicJdbcDAO<T, ID extends Serializable>{
	private EntityInfoManager ef = new EntityInfoManager();
	private SessionFactory sessionFactory;

	protected Class<T> persistentClass;

	public BasicJdbcDAO() {
		this.persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
	}
	
	protected JdbcSession getSession() {
		JdbcSession session = sessionFactory.getCurrentSession();
		return session;
	}

	public Serializable save(final Object entity) {
		return this.getSession().save(entity);
	}

	public void update(final Object entity) {
		this.getSession().update(entity);
	}

	public void delete(final Object entity) {
		this.getSession().delete(entity);
	}

	public void delete(Serializable id) {
		this.getSession().delete(persistentClass, id);
	}

	protected Object queryUnique(final String sql, final Object... values) {
		CachedRowSet rs = this.getSession().executeQuery(sql, values);
		try {
			if(rs.next()){
				return rs.getObject(1);
			}
		} catch (SQLException e) {
			throw new JdbcException(e);
		}
		return null;
	}

	protected int executeUpdate(final String sql, final Object... values) {
		return this.getSession().executeUpdate(sql, values);
	}


	public List<T> findByProperty(String propertyName, Object value){
		String columnName = this.getColumnName(persistentClass, propertyName);
		String tableName = this.getTableName(persistentClass);
		String sql = "select * from "+tableName+" where "+columnName+"=?";
		return this.getSession().query(persistentClass, sql, value);
	}

	public List findPropertyList(String resultProperty, String filterProperty, Object value) {
		String resultColumnName = this.getColumnName(persistentClass, resultProperty);
		String filterColumnName = this.getColumnName(persistentClass, filterProperty);
		String tableName = this.getTableName(persistentClass);
		String sql = "select "+resultColumnName+" from "+tableName+" where "+filterColumnName+"=?";
		
		CachedRowSet rs = this.getSession().executeQuery(sql);
		try {
			List list = ResultMapping.ppToList(rs, resultColumnName);
			return list;
		} catch (SQLException e) {
			throw new JdbcException(e);
		}
	}

	protected T get(Serializable id) {
		return this.getSession().get(persistentClass, id);
	}
	
	private String getTableName(Class<?> clazz){
		EntityInfo ei = ef.getEntityInfo(clazz);
		return ei.getTable();
	}
		
	private String getColumnName(Class<?> clazz, String fieldName){
		EntityInfo ei = ef.getEntityInfo(clazz);
		return ei.getFieldMap().get(fieldName).getColumnName();
	}
}
